import pandas as pd
import numpy as np
from keras import callbacks
from keras.models import load_model
import keras
from keras import backend as K
import keras.optimizers as opt
from keras import Input,layers
from keras.models import Model
from keras import regularizers
"""
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
"""
callback_list = [
        callbacks.EarlyStopping(monitor="val_f1", patience=1000),
        callbacks.ModelCheckpoint(filepath="model_he_1.h5", monitor="val_f1", save_best_only=True),
        callbacks.ReduceLROnPlateau(monitor="val_f1", factor=0.7, verbose=1, patience=5)
    ]
def f1(y_true, y_pred):
    def recall(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
        recall = true_positives / (possible_positives + K.epsilon())
        return recall
    def precision(y_true, y_pred):
        true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
        predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
        precision = true_positives / (predicted_positives + K.epsilon())
        return precision
    precision = precision(y_true, y_pred)
    recall = recall(y_true, y_pred)
    return 2 * ((precision * recall) / (precision + recall + K.epsilon()))
df=pd.read_csv("train.csv")
area={i:j for i,j in zip(list(set(df["area_id"])),range(0,len(list(set(df["area_id"]))),1))}
df_test=df.iloc[600000:,:]
df_train=df.iloc[:600000,:]

for i in range(11):
    df_1=df_train[df_train["is_5g"]==1]
    df_2=df_train[df_train["is_5g"]==0].sample(n=73000)
    df_cut_part=pd.concat([df_1,df_2])
    df_cut_part=df_cut_part.reset_index()
    df_cut_part=df_cut_part.drop("index",axis=1)
    sampler=np.random.permutation(80938)
    df_cut_part=df_cut_part.take(sampler)
    if(i==0):
        df_cut=df_cut_part
    else:
        df_cut=pd.concat([df_cut,df_cut_part])
data=pd.DataFrame(df_cut,columns=['user_id','prov_id', 'area_id',  'chnl_type', 'service_type', 'product_type', 'innet_months', 'total_times', 'total_flux', 'total_fee', 'pay_fee', 'sex', 'age', 'manu_name', 'term_type', 'max_rat_flag', 'is_5g_base_cover', 'is_work_5g_cover', 'is_home_5g_cover', 'is_work_5g_cover_l01', 'is_home_5g_cover_l01', 'is_work_5g_cover_l02', 'is_home_5g_cover_l02', 'activity_type', 'is_act_expire', 'comp_type', 'call_days', 're_call10', 'short_call10', 'long_call10', 'bank_cnt', 'active_days01', 'active_days02', 'active_days03', 'active_days04', 'active_days05', 'active_days06', 'active_days07', 'active_days08', 'active_days09', 'active_days10', 'active_days11', 'active_days12', 'active_days13', 'active_days14', 'active_days15', 'active_days16', 'active_days17', 'active_days18', 'active_days19', 'active_days20', 'active_days21', 'active_days22', 'active_days23', 'game_app_flux', 'live_app_flux', 'video_app_flux', 'city_5g_ratio', 'city_level'])
label=df_cut.iloc[:,59:]
data_test=pd.DataFrame(df_test,columns=['user_id','prov_id', 'area_id',  'chnl_type', 'service_type', 'product_type', 'innet_months', 'total_times', 'total_flux', 'total_fee', 'pay_fee', 'sex', 'age', 'manu_name', 'term_type', 'max_rat_flag', 'is_5g_base_cover', 'is_work_5g_cover', 'is_home_5g_cover', 'is_work_5g_cover_l01', 'is_home_5g_cover_l01', 'is_work_5g_cover_l02', 'is_home_5g_cover_l02', 'activity_type', 'is_act_expire', 'comp_type', 'call_days', 're_call10', 'short_call10', 'long_call10', 'bank_cnt', 'active_days01', 'active_days02', 'active_days03', 'active_days04', 'active_days05', 'active_days06', 'active_days07', 'active_days08', 'active_days09', 'active_days10', 'active_days11', 'active_days12', 'active_days13', 'active_days14', 'active_days15', 'active_days16', 'active_days17', 'active_days18', 'active_days19', 'active_days20', 'active_days21', 'active_days22', 'active_days23', 'game_app_flux', 'live_app_flux', 'video_app_flux', 'city_5g_ratio', 'city_level'])
label_test=df_test.iloc[:,59:]
df_total=pd.DataFrame(df,columns=['user_id','prov_id', 'area_id',  'chnl_type', 'service_type', 'product_type', 'innet_months', 'total_times', 'total_flux', 'total_fee', 'pay_fee', 'sex', 'age', 'manu_name', 'term_type', 'max_rat_flag', 'is_5g_base_cover', 'is_work_5g_cover', 'is_home_5g_cover', 'is_work_5g_cover_l01', 'is_home_5g_cover_l01', 'is_work_5g_cover_l02', 'is_home_5g_cover_l02', 'activity_type', 'is_act_expire', 'comp_type', 'call_days', 're_call10', 'short_call10', 'long_call10', 'bank_cnt', 'active_days01', 'active_days02', 'active_days03', 'active_days04', 'active_days05', 'active_days06', 'active_days07', 'active_days08', 'active_days09', 'active_days10', 'active_days11', 'active_days12', 'active_days13', 'active_days14', 'active_days15', 'active_days16', 'active_days17', 'active_days18', 'active_days19', 'active_days20', 'active_days21', 'active_days22', 'active_days23', 'game_app_flux', 'live_app_flux', 'video_app_flux', 'city_5g_ratio', 'city_level'])

def handle_area(x):
    return area[x]
data['area_id']=data['area_id'].apply(handle_area)
df_total['area_id']=df_total['area_id'].apply(handle_area)
data_test['area_id']=data_test['area_id'].apply(handle_area)


left_two=data[['chnl_type','service_type', 'product_type', 'max_rat_flag','activity_type','is_act_expire', 'comp_type']]
left_two_test=data_test[['chnl_type','service_type', 'product_type', 'max_rat_flag','activity_type','is_act_expire', 'comp_type']]
left_two_total=df_total[['chnl_type','service_type', 'product_type', 'max_rat_flag','activity_type','is_act_expire', 'comp_type']]
left_two=(left_two-left_two_total.mean())/left_two_total.std()
left_two_test=(left_two_test-left_two_total.mean())/left_two_total.std()
left_two=np.array(left_two)
left_two_test=np.array(left_two_test)
left_two_input = Input(shape=(7,))
x = layers.Dense(32, activation="relu")(left_two_input)
x=layers.Dropout(0.25)(x)
x = layers.normalization.BatchNormalization()(x)
x = layers.Dense(64, activation="relu")(x)
x=layers.Dropout(0.25)(x)
x = layers.normalization.BatchNormalization()(x)
x = layers.Dense(64, activation="relu")(x)
x=layers.Dropout(0.25)(x)
x = layers.normalization.BatchNormalization()(x)
x = layers.Dense(7, activation="relu")(x)


total_flux=data[[ 'total_flux']]
total_flux_test=data_test[[ 'total_flux']]
total_flux_total=df_total[[ 'total_flux']]
total_flux=(total_flux-total_flux_total.mean())/total_flux_total.std()
total_flux_test=(total_flux_test-total_flux_total.mean())/total_flux_total.std()
total_flux=np.array(total_flux)
total_flux_test=np.array(total_flux_test)
total_flux_input = Input(shape=(1,))
y = layers.Dense(16, activation="relu")(total_flux_input)
y=layers.Dropout(0.25)(y)
y = layers.normalization.BatchNormalization()(y)
y = layers.Dense(1, activation="relu")(y)


_5g_cover=data[[ 'is_5g_base_cover', 'is_work_5g_cover', 'is_home_5g_cover', 'is_work_5g_cover_l01', 'is_home_5g_cover_l01', 'is_work_5g_cover_l02', 'is_home_5g_cover_l02']]
_5g_cover["5g_total"]=3*(_5g_cover['is_5g_base_cover']+_5g_cover['is_work_5g_cover']+_5g_cover['is_home_5g_cover'])+2*(_5g_cover['is_work_5g_cover_l01']+_5g_cover['is_home_5g_cover_l01'])+_5g_cover["is_work_5g_cover_l02"]+_5g_cover["is_home_5g_cover_l02"]
_5g_cover=_5g_cover["5g_total"]
_5g_cover_total=df_total[[ 'is_5g_base_cover', 'is_work_5g_cover', 'is_home_5g_cover', 'is_work_5g_cover_l01', 'is_home_5g_cover_l01', 'is_work_5g_cover_l02', 'is_home_5g_cover_l02']]
_5g_cover_total["5g_total"]=3*(_5g_cover_total['is_5g_base_cover']+_5g_cover_total['is_work_5g_cover']+_5g_cover_total['is_home_5g_cover'])+2*(_5g_cover_total['is_work_5g_cover_l01']+_5g_cover_total['is_home_5g_cover_l01'])+_5g_cover_total["is_work_5g_cover_l02"]+_5g_cover_total["is_home_5g_cover_l02"]
_5g_cover_total=_5g_cover_total["5g_total"]
_5g_cover_test=data_test[[ 'is_5g_base_cover', 'is_work_5g_cover', 'is_home_5g_cover', 'is_work_5g_cover_l01', 'is_home_5g_cover_l01', 'is_work_5g_cover_l02', 'is_home_5g_cover_l02']]
_5g_cover_test["5g_total"]=3*(_5g_cover_test['is_5g_base_cover']+_5g_cover_test['is_work_5g_cover']+_5g_cover_test['is_home_5g_cover'])+2*(_5g_cover_test['is_work_5g_cover_l01']+_5g_cover_test['is_home_5g_cover_l01'])+_5g_cover_test["is_work_5g_cover_l02"]+_5g_cover_test["is_home_5g_cover_l02"]
_5g_cover_test=_5g_cover_test["5g_total"]
_5g_cover=(_5g_cover-_5g_cover_total.mean())/_5g_cover_total.std()
_5g_cover_test=(_5g_cover_test-_5g_cover_total.mean())/_5g_cover_total.std()
_5g_cover=np.array(_5g_cover)
_5g_cover_test=np.array(_5g_cover_test)
_5g_cover_input = Input(shape=(1,))
z= layers.Dense(16, activation="relu")(_5g_cover_input)
z=layers.Dropout(0.25)(z)
z = layers.normalization.BatchNormalization()(z)
z = layers.Dense(1, activation="relu")(z)



app=data.loc[:,"active_days01":'active_days23']
app["app_sum"]=app.sum(axis=1)
app=app["app_sum"]
app_test=data_test.loc[:,"active_days01":'active_days23']
app_test["app_sum"]=app_test.sum(axis=1)
app_test=app_test["app_sum"]
app_total=df_total.loc[:,"active_days01":'active_days23']
app_total["app_sum"]=app_total.sum(axis=1)
app_total=app_total["app_sum"]
app=(app-app_total.mean())/app_total.std()
app_test=(app_test-app_total.mean())/app_total.std()
app=np.array(app)
app_test=np.array(app_test)
app_input = Input(shape=(1,))
a= layers.Dense(16, activation="relu")(app_input)
a=layers.Dropout(0.25)(a)
a = layers.normalization.BatchNormalization()(a)
a = layers.Dense(1, activation="relu")(a)


app_flux=data[['game_app_flux', 'live_app_flux', 'video_app_flux']]
app_flux["app_flux_sum"]=app_flux.sum(axis=1)
app_flux=app_flux["app_flux_sum"]
app_flux_test=data_test[['game_app_flux', 'live_app_flux', 'video_app_flux']]
app_flux_test["app_flux_sum"]=app_flux_test.sum(axis=1)
app_flux_test=app_flux_test["app_flux_sum"]
app_flux_total=df_total[['game_app_flux', 'live_app_flux', 'video_app_flux']]
app_flux_total["app_flux_sum"]=app_flux_total.sum(axis=1)
app_flux_total=app_flux_total["app_flux_sum"]
app_flux=(app_flux-app_flux_total.mean())/app_flux_total.std()
app_flux_test=(app_flux_test-app_flux_total.mean())/app_flux_total.std()
app_flux=np.array(app_flux)
app_flux_test=np.array(app_flux_test)
app_flux_input = Input(shape=(1,))
b= layers.Dense(16, activation="relu")(app_flux_input)
b=layers.Dropout(0.25)(b)
b = layers.normalization.BatchNormalization()(b)
b = layers.Dense(1, activation="relu")(b)



city=data[['city_5g_ratio', 'city_level']]
city_test=data_test[['city_5g_ratio', 'city_level']]
city_total=df_total[['city_5g_ratio', 'city_level']]
city=(city-city_total.mean())/city_total.std()
city_test=(city_test-city_total.mean())/city_total.std()
city=np.array(city)
city_test=np.array(city_test)
city_input = Input(shape=(2,))
c= layers.Dense(16, activation="relu")(city_input)
c=layers.Dropout(0.25)(c)
c = layers.normalization.BatchNormalization()(c)
c = layers.Dense(2, activation="relu")(c)



call_time=data[['short_call10', 'long_call10']]
call_time["call_time"]=2*data["long_call10"]+data['short_call10']
call_time=call_time["call_time"]
call_time_test=data_test[['short_call10', 'long_call10']]
call_time_test["call_time"]=2*data_test["long_call10"]+data_test['short_call10']
call_time_test=call_time_test["call_time"]
call_time_total=df_total[['short_call10', 'long_call10']]
call_time_total["call_time"]=2*df_total["long_call10"]+df_total['short_call10']
call_time_total=call_time_total["call_time"]
call_time=(call_time-call_time_total.mean())/call_time_total.std()
call_time_test=(call_time_test-call_time_total.mean())/call_time_total.std()
call_time=np.array(call_time)
call_time_test=np.array(call_time_test)
call_time_input = Input(shape=(1,))
d= layers.Dense(16, activation="relu")(call_time_input)
d=layers.Dropout(0.25)(d)
d = layers.normalization.BatchNormalization()(d)
d = layers.Dense(1, activation="relu")(d)



concat=layers.concatenate([x,y,z,a,b,c,d],axis=1)
out = layers.Dense(64, activation="relu")(concat)
out=layers.Dropout(0.25)(out)
out = layers.normalization.BatchNormalization()(out)
out= layers.Dense(128, activation="relu")(out)
out=layers.Dropout(0.25)(out)
out = layers.normalization.BatchNormalization()(out)
out= layers.Dense(128, activation="relu")(out)
out=layers.Dropout(0.25)(out)
out = layers.normalization.BatchNormalization()(out)
out= layers.Dense(1,activation="sigmoid")(out)
model_2=Model([left_two_input,total_flux_input,_5g_cover_input,app_input,app_flux_input,city_input,call_time_input],out)
model_2.compile(optimizer=opt.adam(), loss="binary_crossentropy",metrics=[f1,"acc"])
model_2.fit([left_two,total_flux,_5g_cover,app,app_flux,city,call_time],label, epochs=40000, batch_size=4096, callbacks=callback_list,validation_data=([left_two_test,total_flux_test,_5g_cover_test,app_test,app_flux_test,city_test,call_time_test],label_test))